`include "defines.v"
module user2AXI(
  input clk,
  input rst_n,
  // Icache
  input                 icache_mem_addr_valid_i,
  input  [`PADDR_W-1:0] icache_mem_addr_i,
  output                mem_icache_data_valid_o,
  output [511:0]        mem_icache_data_o,
  // Dcache 
  input                 dcache_mem_addr_valid_i,
  input                 dcache_mem_wen_i,
  input  [`PADDR_W-1:0] dcache_mem_addr_i,
  input  [511:0]        dcache_mem_wdata_i,
  input  [7:0]          dcache_mem_strb_i,
  output                mem_dcache_data_valid_o,
  output [511:0]        mem_dcache_rdata_o,
  // AXI bus
  input                               axi_ar_ready     ,
  output                              axi_ar_valid     ,
  output [`AXI_ADDR_WIDTH-1:0]        axi_ar_bits_addr ,
  output [2:0]                        axi_ar_bits_prot ,
  output [`AXI_ID_WIDTH-1:0]          axi_ar_bits_id   ,
  output [`AXI_USER_WIDTH-1:0]        axi_ar_bits_user ,
  output [7:0]                        axi_ar_bits_len  ,
  output [2:0]                        axi_ar_bits_size ,
  output [1:0]                        axi_ar_bits_burst,
  output                              axi_ar_bits_lock ,
  output [3:0]                        axi_ar_bits_cache,
  output [3:0]                        axi_ar_bits_qos  ,

  output                              axi_r_ready      ,
  input                               axi_r_valid      ,
  input  [1:0]                        axi_r_bits_resp  ,
  input  [`AXI_DATA_WIDTH-1:0]        axi_r_bits_data  ,
  input                               axi_r_bits_last  ,
  input  [`AXI_ID_WIDTH-1:0]          axi_r_bits_id    ,
  input  [`AXI_USER_WIDTH-1:0]        axi_r_bits_user  ,
  
  input                               axi_aw_ready     ,       
  output                              axi_aw_valid     ,   
  output [`AXI_ADDR_WIDTH-1:0]        axi_aw_bits_addr ,   
  output [2:0]                        axi_aw_bits_prot ,   
  output [`AXI_ID_WIDTH-1:0]          axi_aw_bits_id   ,
  output [`AXI_USER_WIDTH-1:0]        axi_aw_bits_user ,     
  output [7:0]                        axi_aw_bits_len  ,      
  output [2:0]                        axi_aw_bits_size ,
  output [1:0]                        axi_aw_bits_burst,
  output                              axi_aw_bits_lock ,   
  output [3:0]                        axi_aw_bits_cache,   
  output [3:0]                        axi_aw_bits_qos  ,   
  
  input                               axi_w_ready      ,  
  output                              axi_w_valid      ,
  output [`AXI_DATA_WIDTH-1:0]        axi_w_bits_data  ,   
  output [`AXI_DATA_WIDTH/8-1:0]      axi_w_bits_strb  ,   
  output                              axi_w_bits_last  ,   
  
  output                              axi_b_ready       ,
  input                               axi_b_valid       ,
  input  [1:0]                        axi_b_bits_resp   ,  
  input  [`AXI_ID_WIDTH-1:0]          axi_b_bits_id     ,
  input  [`AXI_USER_WIDTH-1:0]        axi_b_bits_user    
);
wire dispute_rd_addr_valid;
wire [`PADDR_W-1:0]dispute_rd_addr;
wire dispute_rd_data_valid;
wire [511:0]dispute_rd_data;

wire dispute_wr_addr_valid;
wire [`PADDR_W-1:0]dispute_wr_addr;
wire [7:0] dispute_wr_strb;
wire [511:0]dispute_wr_data;
wire dispute_wr_data_valid;

wire  rd_addr_valid;
wire  [`PADDR_W-1:0]rd_addr;
wire  rd_data_valid;
wire  [511:0]rd_data;

reqDispute reqdispute(
  // user request
  .dcache_mem_addr_valid_i(dcache_mem_addr_valid_i),
  .dcache_mem_wen_i       (dcache_mem_wen_i       ),
  .dcache_mem_strb_i      (dcache_mem_strb_i      ),
  .dcache_mem_addr_i      (dcache_mem_addr_i      ),
  .dcache_mem_wdata_i     (dcache_mem_wdata_i     ),
  .mem_dcache_data_valid_o(mem_dcache_data_valid_o),
  .mem_dcache_rdata_o     (mem_dcache_rdata_o     ),
  // read request
  .rd_addr_valid_o (dispute_rd_addr_valid),
  .rd_addr_o       (dispute_rd_addr),
  .rd_data_valid_i (dispute_rd_data_valid),
  .rd_data_i       (dispute_rd_data),
  // write request
  .wr_addr_valid_o (dispute_wr_addr_valid),
  .wr_addr_o       (dispute_wr_addr),
  .wr_strb_o       (dispute_wr_strb),
  .wr_data_o       (dispute_wr_data),
  .wr_data_valid_i (dispute_wr_data_valid)
);

rdArbiter rdArb(
  .clk(clk),
  .rst_n(rst_n),

  .rd1_addr_valid_i(icache_mem_addr_valid_i),
  .rd1_addr_i(icache_mem_addr_i),
  .rd1_data_valid_o(mem_icache_data_valid_o),
  .rd1_data_o(mem_icache_data_o),

  .rd2_addr_valid_i (dispute_rd_addr_valid),
  .rd2_addr_i       (dispute_rd_addr),
  .rd2_data_valid_o (dispute_rd_data_valid),
  .rd2_data_o       (dispute_rd_data),

  .rd_addr_valid_o  (rd_addr_valid ),
  .rd_addr_o        (rd_addr       ),
  .rd_data_valid_i  (rd_data_valid ),
  .rd_data_i        (rd_data       )
);

rdAXI rd2axi(
  .clk(clk),
  .rst_n(rst_n),

  .rd_addr_valid_i (rd_addr_valid ),
  .rd_addr_i       (rd_addr       ),
  .rd_data_valid_o (rd_data_valid ),
  .rd_data_o       (rd_data       ),

  .axi_ar_ready      (axi_ar_ready     ),
  .axi_ar_valid      (axi_ar_valid     ),
  .axi_ar_bits_addr  (axi_ar_bits_addr ),
  .axi_ar_bits_prot  (axi_ar_bits_prot ),
  .axi_ar_bits_id    (axi_ar_bits_id   ),
  .axi_ar_bits_user  (axi_ar_bits_user ),
  .axi_ar_bits_len   (axi_ar_bits_len  ),
  .axi_ar_bits_size  (axi_ar_bits_size ),
  .axi_ar_bits_burst (axi_ar_bits_burst),
  .axi_ar_bits_lock  (axi_ar_bits_lock ),
  .axi_ar_bits_cache (axi_ar_bits_cache),
  .axi_ar_bits_qos   (axi_ar_bits_qos  ),

  .axi_r_ready     (axi_r_ready     ),
  .axi_r_valid     (axi_r_valid     ),
  .axi_r_bits_resp (axi_r_bits_resp ),
  .axi_r_bits_data (axi_r_bits_data ),
  .axi_r_bits_last (axi_r_bits_last ),
  .axi_r_bits_id   (axi_r_bits_id   ),
  .axi_r_bits_user (axi_r_bits_user )
);

wrAXI wr2axi(
  .clk(clk),
  .rst_n(rst_n),
  
  .wr_addr_valid_i (dispute_wr_addr_valid),
  .wr_addr_i       (dispute_wr_addr),
  .wr_strb_i       (dispute_wr_strb),
  .wr_data_i       (dispute_wr_data),
  .wr_data_valid_o (dispute_wr_data_valid),

  .axi_aw_ready     (axi_aw_ready     ),       
  .axi_aw_valid     (axi_aw_valid     ),   
  .axi_aw_bits_addr (axi_aw_bits_addr ),   
  .axi_aw_bits_prot (axi_aw_bits_prot ),   
  .axi_aw_bits_id   (axi_aw_bits_id   ),
  .axi_aw_bits_user (axi_aw_bits_user ),     
  .axi_aw_bits_len  (axi_aw_bits_len  ),      
  .axi_aw_bits_size (axi_aw_bits_size ),
  .axi_aw_bits_burst(axi_aw_bits_burst),
  .axi_aw_bits_lock (axi_aw_bits_lock ),   
  .axi_aw_bits_cache(axi_aw_bits_cache),   
  .axi_aw_bits_qos  (axi_aw_bits_qos  ),   
  
  .axi_w_ready     (axi_w_ready    ) ,  
  .axi_w_valid     (axi_w_valid    ) ,
  .axi_w_bits_data (axi_w_bits_data) ,   
  .axi_w_bits_strb (axi_w_bits_strb) ,   
  .axi_w_bits_last (axi_w_bits_last) ,   
  
  .axi_b_ready      (axi_b_ready     ),
  .axi_b_valid      (axi_b_valid     ),
  .axi_b_bits_resp  (axi_b_bits_resp ),  
  .axi_b_bits_id    (axi_b_bits_id   ),
  .axi_b_bits_user  (axi_b_bits_user ) 
);

// reg [`XLEN-1:0] timee;
// always@(posedge clk or negedge rst_n)
//   if(~rst_n)
//     timee <= `ZERO;
//   else 
//     timee <= timee + 1'b1;

// always@(posedge clk )begin
//   if((axi_ar_bits_addr[31:0] == 32'h801d46b0) && axi_ar_valid && axi_ar_ready)
//     $fwrite(32'h8000_0001, "RD addr [%x] time %d \n",axi_ar_bits_addr , timee);
//  if((axi_aw_bits_addr[31:0] == 32'h801d46b0) && axi_aw_valid && axi_aw_ready)
//     $fwrite(32'h8000_0001, "WR addr [%x] time %d \n",axi_aw_bits_addr , timee);
// end
endmodule